package mnnu.ghbe.service;

import com.openai.client.OpenAIClient;
import com.openai.client.okhttp.OpenAIOkHttpClient;
import com.openai.core.JsonValue;
import com.openai.core.http.StreamResponse;
import com.openai.models.chat.completions.ChatCompletion;
import com.openai.models.chat.completions.ChatCompletionChunk;
import com.openai.models.chat.completions.ChatCompletionCreateParams;
import com.openai.models.chat.completions.ChatCompletionContentPart;
import com.openai.models.chat.completions.ChatCompletionContentPartImage;
import com.openai.models.chat.completions.ChatCompletionContentPartText;
import mnnu.ghbe.config.OpenAIConfig;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyEmitter;

import jakarta.annotation.PostConstruct;

import java.io.IOException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * OpenAI服务类
 * 提供与OpenAI API交互的功能
 */
@Service
public class OpenAIService {
    
    @Autowired
    private OpenAIConfig openAIConfig;
    
    private OpenAIClient openAIClient;
    
    @PostConstruct
    public void init() {
        // 使用构建器模式创建OpenAI客户端实例
        this.openAIClient = OpenAIOkHttpClient.builder()
                .apiKey(openAIConfig.getApiKey())
                .baseUrl(openAIConfig.getBaseUrl())
                .build();
    }
    
    /**
     * 获取OpenAIClient实例
     * 
     * @return OpenAIClient实例
     */
    public OpenAIClient getOpenAIClient() {
        return openAIClient;
    }

    /**
     * 调用OpenAI聊天接口
     * 
     * @param model 模型名称
     * @param content 用户消息内容
     * @param prompt 系统提示词
     * @return ChatCompletion响应
     * @throws Exception API调用异常
     */
    public ChatCompletion chat(String model, String content, String prompt) throws Exception {
        Map<String, JsonValue> extraBodyParams = new HashMap<>();
        extraBodyParams.put("enable_thinking", JsonValue.from(false));
        ChatCompletionCreateParams params = ChatCompletionCreateParams.builder()
                .model(model)
                .addSystemMessage(prompt)
                .addUserMessage(content)
                .additionalBodyProperties(extraBodyParams)
                .build();
        
        return openAIClient.chat().completions().create(params);
    }
    
    /**
     * 调用OpenAI聊天接口并返回字符串结果
     * 
     * @param model 模型名称
     * @param content 用户消息内容
     * @param prompt 系统提示词
     * @return AI回复的文本内容
     * @throws Exception API调用异常
     */
    public String chatWithModel(String model, String content, String prompt) throws Exception {
        ChatCompletion response = chat(model, content, prompt);
        return response.choices().get(0).message().content().orElse("");
    }
    
    /**
     * 调用OpenAI VLM模型进行OCR识别
     * 
     * @param imageDataUrl 图片的Base64数据URL
     * @return OCR识别结果
     * @throws Exception API调用异常
     */
    public String ocrWithModel(String imageDataUrl) throws Exception {
        Map<String, JsonValue> extraBodyParams = new HashMap<>();
        extraBodyParams.put("enable_thinking", JsonValue.from(false));
        
        ChatCompletionContentPart imageContentPart = 
                ChatCompletionContentPart.ofImageUrl(ChatCompletionContentPartImage.builder()
                        .imageUrl(ChatCompletionContentPartImage.ImageUrl.builder()
                                .url(imageDataUrl)
                                .build())
                        .build());
        
        ChatCompletionCreateParams params = ChatCompletionCreateParams.builder()
                .model(openAIConfig.getModelName())
                .addSystemMessage(openAIConfig.getOcrPrompt())
                .addUserMessageOfArrayOfContentParts(List.of(imageContentPart))
                .additionalBodyProperties(extraBodyParams)
                .build();
        
        ChatCompletion response = openAIClient.chat().completions().create(params);
        return response.choices().get(0).message().content().orElse("");
    }
    
    /**
     * 调用OpenAI VLM模型进行OCR识别（支持自定义提示词）
     * 
     * @param imageDataUrl 图片的Base64数据URL
     * @param prompt OCR识别提示词
     * @return OCR识别结果
     * @throws Exception API调用异常
     */
    public String ocrWithModel(String imageDataUrl, String prompt) throws Exception {
        Map<String, JsonValue> extraBodyParams = new HashMap<>();
        extraBodyParams.put("enable_thinking", JsonValue.from(false));
        
        ChatCompletionContentPart imageContentPart = 
                ChatCompletionContentPart.ofImageUrl(ChatCompletionContentPartImage.builder()
                        .imageUrl(ChatCompletionContentPartImage.ImageUrl.builder()
                                .url(imageDataUrl)
                                .build())
                        .build());
        
        ChatCompletionCreateParams params = ChatCompletionCreateParams.builder()
                .model(openAIConfig.getModelName())
                .addSystemMessage(prompt)
                .addUserMessageOfArrayOfContentParts(List.of(imageContentPart))
                .additionalBodyProperties(extraBodyParams)
                .build();
        
        ChatCompletion response = openAIClient.chat().completions().create(params);
        return response.choices().get(0).message().content().orElse("");
    }
    
    /**
     * 调用OpenAI聊天接口并流式返回结果
     * 
     * @param model 模型名称
     * @param content 用户消息内容
     * @param prompt 系统提示词
     * @param emitter SSE 发射器
     * @throws Exception API调用异常
     */
    public void streamChatWithModel(String model, String content, String prompt, ResponseBodyEmitter emitter) throws Exception {
        
        // 构建流式请求参数
        Map<String, JsonValue> streamParams = new HashMap<>();
        streamParams.put("enable_thinking", JsonValue.from(false));
        streamParams.put("stream", JsonValue.from(true));
        
        ChatCompletionCreateParams params = ChatCompletionCreateParams.builder()
                .model(model)
                .addSystemMessage(prompt)
                .addUserMessage(content)
                .additionalBodyProperties(streamParams)
                .build();
                
        try (StreamResponse<ChatCompletionChunk> streamResponse = openAIClient.chat().completions().createStreaming(params)) {
            streamResponse.stream().forEach(chunk -> {
                try {
                    if (chunk.choices() != null && !chunk.choices().isEmpty()) {
                        String delta = chunk.choices().get(0).delta().content().orElse("");
                        if (!delta.isEmpty()) {
                            emitter.send(delta);
                        }
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                }
            });
            emitter.complete();
        } catch (Exception e) {
            emitter.completeWithError(e);
        }
    }
}